package com.thenie.chat.controller;

import cn.hutool.json.JSONUtil;
import com.thenie.chat.service.IDialogSocketService;
import com.thenie.chat.util.WebSocketUtil;
import com.thenie.chat.vo.DialogMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.thenie.chat.config.RabbitmqConfig.EXCHANGE_DIRECT_ONLINE;

/**
 * @Description 好友聊天处理器（/ws/dialog?userId=）
 * @Author thenie
 * @Data 2022/5/28 18:26
 */
@Component
@Slf4j
public class DialogSocketHandler extends AbstractWebSocketHandler {

    @Autowired
    private IDialogSocketService dialogSocketService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public static final Map<String,WebSocketSession> SESSION_MAP = new ConcurrentHashMap<>(32);



    /**
     * 连接成功后调用
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        String userId = WebSocketUtil.getUserId(session);
        SESSION_MAP.put(userId,session);

        //通知好友们已上线
        rabbitTemplate.convertAndSend(EXCHANGE_DIRECT_ONLINE,"onlineUp",Long.valueOf(userId));

        log.info("用户id:{}上线", userId);
        //查看是否有自己的离线消息
        if (dialogSocketService.existOfflineMessageForMe(userId)){
            //获取消息
            List<Object> messageList = dialogSocketService.getAllOfflineMessage(userId);
            //删除已获取的消息
            dialogSocketService.removeOfflineMessageForMe(userId);

            WebSocketUtil.sendOfflineMessage(session,messageList);

        }

    }


    /**
     * 转发消息
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) {
        //获取消息
        String jsonMessage = message.getPayload();
        DialogMessage dialogMessage = JSONUtil.toBean(jsonMessage, DialogMessage.class);
        //获取接收方id
        String toFriendId = dialogMessage.getToFriendId();
        WebSocketSession toFriendSession = SESSION_MAP.get(toFriendId);
        //判断接收方是否在线
        if (toFriendSession == null){
            //离线，把消息保存到redis中
            dialogSocketService.saveOfflineMessage(dialogMessage);
        }else{
            //在线，直接发送消息
//            toFriendSession.sendMessage(new TextMessage(JSONUtil.toJsonStr(dialogMessage)));
            WebSocketUtil.sendMessage(toFriendSession,dialogMessage);
        }

    }


    @Override
    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
    }

    @Override
    protected void handlePongMessage(WebSocketSession session, PongMessage message) {
    }
    /**
     * WS 连接出错时调用
     * @param session
     * @param exception
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) {
        log.error("webSocket连接出错:{}",exception);
    }

    /**
     * 连接关闭后调用
     * @param session
     * @param closeStatus
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
        String userId = WebSocketUtil.getUserId(session);
        if (SESSION_MAP.containsKey(userId)){
            SESSION_MAP.remove(userId);
            //通知好友们下线
            rabbitTemplate.convertAndSend(EXCHANGE_DIRECT_ONLINE,"onlineDown",Long.valueOf(userId));
            log.info("用户id:{}下线",userId);
        }
    }

    /**
     * 是否支持分片消息
     * @return
     */
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

}
